package com.cmes.core;

import com.cmes.core.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 统一数据交互格式
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@NoArgsConstructor
@Data
public class ResponseData<T> implements Serializable {

    /**
     * 响应成功，默认提示信息
     */
    public static final String DEFAULT_SUCCESS_INFO = "操作成功";

    /**
     * 响应失败，默认提示信息
     */
    public static final String DEFAULT_FAIL_INFO = "操作失败";

    /**
     * 响应状态，true表示成功，false表示失败
     */
    private boolean status;

    /**
     * 响应提示
     */
    private String message;

    /**
     * 响应数据
     */
    private T data;

    /**
     * traceId
     */
    private String traceId;

    /**
     * 是否成功响应
     *
     * @return true | false
     */
    @JsonIgnore
    public boolean isOk() {
        return this.status;
    }

    /**
     * 是否成功响应
     *
     * @return true | false
     */
    @JsonIgnore
    public boolean nonOk() {
        return !this.status;
    }

    /**
     * 响应成功，使用 {@link #DEFAULT_SUCCESS_INFO} 进行响应
     *
     * @return ResponseData
     * @see #ok(String, Object)
     */
    public ResponseData<T> ok() {
        return this.ok("", null);
    }

    /**
     * 响应成功，使用 {@link #DEFAULT_SUCCESS_INFO} 进行响应
     *
     * @param data 响应数据
     * @return ResponseData
     * @see #ok(String, Object)
     */
    public ResponseData<T> ok(T data) {
        return this.ok(null, data);
    }

    /**
     * 响应成功，如果 message 为空，则使用 {@link #DEFAULT_SUCCESS_INFO} 进行响应
     *
     * @param info 操作成功提示
     * @param data 业务数据
     * @return ResponseData
     */
    public ResponseData<T> ok(String info, T data) {
        if (StringUtils.isNotEmpty(info)) {
            this.status = true;
            this.message = info;
            this.data = data;
            return this;
        } else {
            return this.ok(DEFAULT_SUCCESS_INFO, data);
        }
    }

    /**
     * 响应失败，使用 {@link #DEFAULT_FAIL_INFO} 进行响应
     *
     * @return ResponseData
     * @see #fail(String, Object)
     */
    public ResponseData<T> fail() {
        return this.fail("", null);
    }

    /**
     * 响应失败，如果 message 为空，则使用 {@link #DEFAULT_FAIL_INFO} 进行响应
     *
     * @param info 提示语
     * @return ResponseData
     * @see #fail(String, Object)
     */
    public ResponseData<T> fail(String info) {
        return this.fail(info, null);
    }

    /**
     * 响应失败，如果 message 为空，则使用 {@link #DEFAULT_FAIL_INFO} 进行响应
     *
     * @param info 提示语
     * @param data 业务数据
     * @return ResponseData
     */
    private ResponseData<T> fail(String info, T data) {
        if (StringUtils.isNotEmpty(info)) {
            this.status = false;
            this.message = info;
            this.data = data;
            return this;
        } else {
            return this.fail(DEFAULT_FAIL_INFO, data);
        }
    }

    /**
     * 响应失败
     *
     * @param errorCode 错误码
     * @return ResponseData
     */
    public ResponseData<T> fail(ResponseCode errorCode, Object... params) {
        return this.fail(errorCode.format(params));
    }

    /**
     * 响应失败
     *
     * @param exception 异常
     * @return ResponseData
     */
    public ResponseData<T> fail(ResponseData<?> exception) {
        return this.fail(exception.getMessage());
    }

    /**
     * 响应失败
     *
     * @param exception 异常
     * @return ResponseData
     */
    public ResponseData<T> fail(Exception exception) {
        return this.fail(exception.getMessage());
    }

    /**
     * 设置 traceId
     *
     * @param traceId traceId
     * @return ResponseData
     */
    public ResponseData<T> traceId(String traceId) {
        this.traceId = traceId;
        return this;
    }

}
